#include "Renderer.h"
/**
    必须在 #include "stb_image.h" 之前定义 STB_IMAGE_IMPLEMENTATION
    By defining STB_IMAGE_IMPLEMENTATION the preprocessor modifies the header
   file such that it only contains the relevant definition source code,
   effectively turning the header file into a .cpp file, and that's about it.
   Now simply include stb_image.h somewhere in your program and compile.
*/
#define STB_IMAGE_IMPLEMENTATION

#include "stb_image.h"
/**
    Using glUniform1i we can actually assign a location value to the texture
   sampler so we can set multiple textures at once in a fragment shader. This
   location of a texture is more commonly known as a texture unit. The default
   texture unit for a texture is 0 which is the default active texture unit so
   we didn't need to assign a location in the previous section

    The main purpose of texture units is to allow us to use more than 1 texture
   in our shaders. By assigning texture units to the samplers, we can bind to
   multiple textures at once as long as we activate the corresponding texture
   unit first. Just like glBindTexture we can activate texture units using
   glActiveTexture passing in the texture unit we'd like to use
*/
unsigned int Renderer::loadTexture(string path, GLenum activatedTexture, GLenum format)
{

    // 1、创建纹理对象
    unsigned int texture;
    glGenTextures(1, &texture);

    // 2、绑定纹理对象
    /**
    After activating a texture unit, a subsequent glBindTexture call will
       bind that texture to the currently active texture unit. Texture unit
       GL_TEXTURE0 is always by default activated
    */
    glActiveTexture(activatedTexture); // 明确指定纹理单元，避免依赖默认状态
    glBindTexture(GL_TEXTURE_2D, texture);

        // set the texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// set texture wrapping to GL_REPEAT (default wrapping method)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 3、使用 stb_image 库来加载纹理资源
    int width, height, numberOfColorChannels;
    unsigned char* data =
        stbi_load(path.c_str(), &width, &height, &numberOfColorChannels, 0);
    if (data)
    {
        // 4、根据已加载的图片来生成纹理
        glTexImage2D(GL_TEXTURE_2D,
                     0,      //  mipmap level，这里0保持默认
                     format, // 最终纹理内部存储的格式
                     width, height,
                     0, // some legacy stuff,应该总是为0
                     format,
                     GL_UNSIGNED_BYTE, // 指定源文件(jpg)的格式和数据类型
                     data);

        /*
        1、 we could call glGenerateMipmap after generating the texture. This
        will automatically generate all the required mipmaps for the currently
        bound texture. 2、 To solve this issue OpenGL uses a concept called
        mipmaps that is basically a collection of texture images where each
        subsequent texture is twice as small compared to the previous one. The
        idea behind mipmaps should be easy to understand: after a certain
        distance threshold from the viewer, OpenGL will use a different mipmap
        texture that best suits the distance to the object. Because the object
        is far away, the smaller resolution will not be noticeable to the user.
        OpenGL is then able to sample the correct texels, and there's less cache
        memory involved when sampling that part of the mipmaps.

        */
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        cout << "failed to load texture jpg file " << endl;
    }
    // 释放图片的内存资源
    stbi_image_free(data);

    return texture;
}